package com.ruoyi.common.utils.sql;

import com.mybatisflex.annotation.Column;
import com.mybatisflex.core.query.QueryWrapper;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 根据请求参数构建查询条件
 * @Author: liu
 * @Create: 2023-04-23
 */
@Slf4j
public class BuildPageRequest {


    /**
     * 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成
     *
     * @param searchObj    查询实体
     * @param parameterMap request.getParameterMap()
     * @return QueryWrapper实例
     */
    public static <T> QueryWrapper initQueryWrapper(T searchObj, Map<String, String[]> parameterMap) throws ParseException {
        long start = System.currentTimeMillis();
        QueryWrapper queryWrapper = new QueryWrapper();
        installMplus(queryWrapper, searchObj, parameterMap);
        log.debug("---查询条件构造器初始化完成,耗时:" + (System.currentTimeMillis() - start) + "毫秒----");
        return queryWrapper;
    }

    private static <T> void installMplus(QueryWrapper queryWrapper, T searchObj, Map<String, String[]> parameterMap) throws ParseException {
        PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(searchObj);
        Map<String, Object> fieldColumnMap = new HashMap<>(5);

        for (PropertyDescriptor origDescriptor : origDescriptors) {
            String name = origDescriptor.getName();
            String type = origDescriptor.getPropertyType().toString();
            String tableFieldName = getTableFieldName(searchObj.getClass(), name);
            if (tableFieldName == null) {
                //不用处理了
                continue;
            }
            if (!parameterMap.containsKey(name)) {
                //不用处理了
                continue;
            }
            String value = parameterMap.get(name)[0].trim();
            if (StringUtils.isNotEmpty(value)) {
                fieldColumnMap.put(name, parseByType(value, type));
            }
        }
        queryWrapper.where(fieldColumnMap);
    }

    /**
     * 获取表字段名
     *
     * @param clazz
     * @param name
     * @return
     */
    private static String getTableFieldName(Class<?> clazz, String name) {
        try {
            Field field = null;
            try {
                field = clazz.getDeclaredField(name);
            } catch (NoSuchFieldException e) {
                //e.printStackTrace();
            }

            //如果为空，则去父类查找字段
            if (field == null) {
                List<Field> allFields = getClassFields(clazz);
                List<Field> searchFields = allFields.stream().filter(a -> a.getName().equals(name)).collect(Collectors.toList());
                if (searchFields != null && searchFields.size() > 0) {
                    field = searchFields.get(0);
                }
            }

            if (field != null) {
                Column tableField = field.getAnnotation(Column.class);
                if (tableField != null) {
                    if (tableField.ignore() == true) {
                        //如果设置了TableField false 这个字段不需要处理
                        return null;
                    } else {
                        String column = tableField.value();
                        //如果设置了TableField value 这个字段是实体字段
                        if (!"".equals(column)) {
                            return column;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return name;
    }

    /**
     * 获取class的 包括父类的
     *
     * @param clazz
     * @return
     */
    private static List<Field> getClassFields(Class<?> clazz) {
        List<Field> list = new ArrayList<Field>();
        Field[] fields;
        do {
            fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                list.add(fields[i]);
            }
            clazz = clazz.getSuperclass();
        } while (clazz != Object.class && clazz != null);
        return list;
    }

    /**
     * 根据类型转换给定的值
     *
     * @param value
     * @param type
     * @return
     * @throws ParseException
     */
    private static Object parseByType(String value, String type) throws ParseException {
        Object temp;
        switch (type) {
            case "class java.lang.Integer":
                temp = Integer.parseInt(value);
                break;
            case "class java.math.BigDecimal":
                temp = new BigDecimal(value);
                break;
            case "class java.lang.Short":
                temp = Short.parseShort(value);
                break;
            case "class java.lang.Long":
                temp = Long.parseLong(value);
                break;
            case "class java.lang.Float":
                temp = Float.parseFloat(value);
                break;
            case "class java.lang.Double":
                temp = Double.parseDouble(value);
                break;
            case "class java.util.Date":
                temp = Date.parse(value);
                break;
            default:
                temp = value;
                break;
        }
        return temp;
    }
}
